//
// Created by pzw on 24-3-26.
//

#ifndef QTTEST_STDALLOC_H
#define QTTEST_STDALLOC_H

#include <vector>
#include <complex>
#include <iostream>

template<typename T, typename... Alloc>
void Log_vec(std::vector<T, Alloc...> vs, std::string tag, std::string vs_name);

template<typename P>
class pointer_traits;

template<typename T, typename... Alloc>
class StdAlloc {
public:/* 分配器概述 */
    static int alloc_summary();
public:/* 默认分配器 */
    static int std_default_alloc();
public:/* 分配器萃取 */
    template<typename A>
    struct allocator_traits {/* 分配器性状，这里稍微列举下，里面的using都可以萃取 */
        using allocator_type = A;
        using value_type = typename A::value_type;
        using pointer = value_type;
        using const_pointer = typename pointer_traits<pointer>::template rebind<const value_type>;
        /* ... */
    };
public:/* 指针萃取 */
    template<typename P>
    struct pointer_traits {
        using pointer = P;
        using element_type = T;
        template<typename U>
        using rebind = T *;

        static pointer pointer_to(T x) noexcept {
            return std::addressof(x);
        }
    };

public:/* 限域的分配器 */
};

template<typename T>
struct Simple_alloc {
    using value_type = T;

    Simple_alloc() = default;

    T *allocate(size_t n) {
        return reinterpret_cast<T *>(new char[n * sizeof(T)]);
    }

    void deallocate(T *p, size_t n) {
        delete[] reinterpret_cast<char *>(p);
    }
};

class Arena {
private:
    void *ptr;
    int sz;

public:
    /* 从 ptr[0...sz-1] 分配空间*/
    explicit Arena(void *ptr, int sz) : ptr(ptr), sz(sz) {
    }
};

template<typename T>
struct My_alloc {
    using value_type = T;

    Arena &arena;

    explicit My_alloc(Arena &aa) : arena(aa) {}

    My_alloc() = default;

    T *allocate(size_t n) {
        return reinterpret_cast<T *>(new char[n * sizeof(T)]);
    }

    void deallocate(T *p, size_t n) {
        delete[] reinterpret_cast<char *>(p);
    }
};

/* 通常我们可以使用别名来简化冗长的描述 */
template<typename T> using Arena_vec = std::vector<T, My_alloc<T>>;
template<typename T> using Simple_vec = std::vector<T, Simple_alloc<T>>;

/* 默认构造器，我们重写一下标准库的默认构造器，来全面了解下 */
template<typename T>
class default_allocator {
public:
    using size_type = size_t;
    using difference_type = ptrdiff_t;
    using pointer = T *;
    using const_pointer = const T *;
    using reference = T &;
    using const_reference = const T &;
    using value_type = T;
    template<typename U>
    struct rebind {
        using other = default_allocator<U>;
    };

public:
    default_allocator() noexcept = default;
    default_allocator(const default_allocator &alloc) noexcept = default;

    template<typename U>
    explicit default_allocator(const default_allocator<U> &) noexcept {};
    ~default_allocator() = default;

public:
    pointer address(reference x) const noexcept {};

    const_pointer address(const_reference x) const noexcept {};

public:
    pointer allocate(size_type n) {};

    void deallocate(pointer p, size_type n) {};

public:
    size_type max_size() const noexcept {};

public:
    template<typename U, typename... Args>
    void construct(U *p, Args &&...args) {};
    template<typename U>
    void destroy(U *p) = delete;

};

template<typename T>
using DefAlloc_vec = std::vector<T, default_allocator<T>>;


int StlAllocator_main();

#endif //QTTEST_STDALLOC_H
